#include "esp32_live_stream.h"
#include "board.h"
#include "application.h"

#include <esp_log.h>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cJSON.h>
#include <vector>
#include <memory>
#include <cstring>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#define TAG "Esp32LiveStream"

Esp32LiveStream::Esp32LiveStream() {
    ESP_LOGI(TAG, "LiveStream initialized");
}

Esp32LiveStream::~Esp32LiveStream() {
    if (streaming_) {
        StopStream();
    }
    if (is_fetching_chat_) {
        StopFetchingChatData();
    }
    if (stream_thread_.joinable()) {
        stream_thread_.join();
    }
    ESP_LOGI(TAG, "LiveStream destroyed");
}

void Esp32LiveStream::SetStreamConfig(const std::string& url, const std::string& token) {
    stream_url_ = url;
    stream_token_ = token;
    // ESP_LOGI(TAG, "Stream config set: url=%s", url.c_str());
}

bool Esp32LiveStream::StartStream(const std::string& stream_id) {
    if (streaming_) {
        ESP_LOGW(TAG, "Stream already running");
        return false;
    }
    
    ESP_LOGI(TAG, "Starting stream with ID: %s", stream_id.c_str());
    
    // TODO: 实现直播功能
    streaming_ = true;
    
    // 启动聊天数据获取
    bool chat_started = StartFetchingChatData();
    if (!chat_started) {
        ESP_LOGW(TAG, "Failed to start chat data fetching, but stream will continue");
    }
    
    return true;
}

bool Esp32LiveStream::StopStream() {
    if (!streaming_) {
        ESP_LOGW(TAG, "Stream not running");
        return false;
    }
    
    ESP_LOGI(TAG, "Stopping stream");
    
    // 停止聊天数据获取
    StopFetchingChatData();
    
    // TODO: 实现停止直播功能
    streaming_ = false;
    
    if (stream_thread_.joinable()) {
        stream_thread_.join();
    }
    
    return true;
}

std::string Esp32LiveStream::GetStreamInfo() const {
    std::string info = "{";
    info += "\"streaming\":" + std::string(streaming_ ? "true" : "false") + ",";
    info += "\"stream_url\":\"" + stream_url_ + "\",";
    info += "\"has_token\":" + std::string(stream_token_.empty() ? "false" : "true");
    info += "}";
    return info;
}

std::string Esp32LiveStream::FetchChatData() {
    auto start_total = std::chrono::steady_clock::now();
    
    auto& board = Board::GetInstance();
    
    // 阶段1：URL构建
    auto start_url_build = std::chrono::steady_clock::now();
    
    std::string url = "http://192.168.0.14:8080/api/messages/chat";

    
    auto end_url_build = std::chrono::steady_clock::now();
    auto url_build_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_url_build - start_url_build).count();
    
    // ESP_LOGI(TAG, "Requesting chat data from: %s", url.c_str());
    ESP_LOGD(TAG, "HTTP timing - URL build: %d ms", (int)url_build_time);
    
    // 阶段2：HTTP连接建立
    auto start_connection = std::chrono::steady_clock::now();
    auto http = board.CreateHttp();
    auto end_create_http = std::chrono::steady_clock::now();
    auto create_http_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_create_http - start_connection).count();
    
    if (!http->Open("GET", url)) {
        auto end_connection = std::chrono::steady_clock::now();
        auto connection_fail_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_connection - start_connection).count();
        ESP_LOGE(TAG, "Failed to connect to chat server - Total connection attempt: %d ms", (int)connection_fail_time);
        return "";
    }
    
    auto end_connection = std::chrono::steady_clock::now();
    auto connection_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_connection - start_connection).count();
    
    ESP_LOGD(TAG, "HTTP timing - Create HTTP: %d ms, Connection: %d ms", (int)create_http_time, (int)connection_time);
    
    // 阶段3：状态码检查
    auto start_status_check = std::chrono::steady_clock::now();
    int status_code = http->GetStatusCode();
    auto end_status_check = std::chrono::steady_clock::now();
    auto status_check_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_status_check - start_status_check).count();
    
    if (status_code != 200) {
        ESP_LOGE(TAG, "Failed to fetch chat data, status code: %d, Status check time: %d ms", status_code, (int)status_check_time);
        http->Close();
        return "";
    }
    
    ESP_LOGD(TAG, "HTTP timing - Status check: %d ms, Status code: %d", (int)status_check_time, status_code);
    
    // 阶段4：数据读取
    auto start_data_read = std::chrono::steady_clock::now();
    std::string result = http->ReadAll();
    auto end_data_read = std::chrono::steady_clock::now();
    auto data_read_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_data_read - start_data_read).count();
    
    // 阶段5：连接关闭
    auto start_close = std::chrono::steady_clock::now();
    http->Close();
    auto end_close = std::chrono::steady_clock::now();
    auto close_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_close - start_close).count();
    
    auto end_total = std::chrono::steady_clock::now();
    auto total_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_total - start_total).count();
    
    ESP_LOGD(TAG, "HTTP timing - Data read: %d ms (%d bytes), Close: %d ms", 
             (int)data_read_time, (int)result.length(), (int)close_time);
    ESP_LOGD(TAG, "HTTP timing - TOTAL HTTP REQUEST: %d ms", (int)total_time);
    
    // 计算传输速度
    if (data_read_time > 0 && result.length() > 0) {
        double speed_kbps = ((double)result.length() / 1024.0) / ((double)data_read_time / 1000.0);
        // ESP_LOGI(TAG, "HTTP performance - Transfer speed: %.2f KB/s", speed_kbps);
    }
    
    return result;
}

bool Esp32LiveStream::StartFetchingChatData() {
    if (is_fetching_chat_) {
        ESP_LOGW(TAG, "Chat data fetching is already running");
        return true;
    }
    
    ESP_LOGI(TAG, "Starting chat data fetching via timer polling...");
    
    // 创建定时器配置
    esp_timer_create_args_t timer_args = {
        .callback = ChatTimerCallback,
        .arg = this,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "chat_fetch_timer"
    };
    
    // 创建定时器
    esp_err_t ret = esp_timer_create(&timer_args, &chat_timer_);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to create chat timer: %s", esp_err_to_name(ret));
        return false;
    }
    
    // 启动定时器，每1秒触发一次
    ret = esp_timer_start_periodic(chat_timer_, CHAT_FETCH_INTERVAL_MS * 1000);  // 转换为微秒
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to start chat timer: %s", esp_err_to_name(ret));
        esp_timer_delete(chat_timer_);
        chat_timer_ = nullptr;
        return false;
    }
    
    is_fetching_chat_ = true;
    has_fetched_in_current_listening_ = false;  // 重置获取标志
    ESP_LOGI(TAG, "Chat data fetching started successfully with %d ms interval", CHAT_FETCH_INTERVAL_MS);
    return true;
}

bool Esp32LiveStream::StopFetchingChatData() {
    if (!is_fetching_chat_) {
        ESP_LOGW(TAG, "Chat data fetching is not running");
        return true;
    }
    
    ESP_LOGI(TAG, "Stopping chat data fetching...");
    
    // 先设置状态为停止
    is_fetching_chat_ = false;
    ESP_LOGI(TAG, "Chat data fetching state set to stopped");
    
    // 停止并删除定时器
    if (chat_timer_) {
        esp_err_t ret = esp_timer_stop(chat_timer_);
        if (ret != ESP_OK) {
            ESP_LOGW(TAG, "Failed to stop chat timer: %s", esp_err_to_name(ret));
        }
        
        ret = esp_timer_delete(chat_timer_);
        if (ret != ESP_OK) {
            ESP_LOGW(TAG, "Failed to delete chat timer: %s", esp_err_to_name(ret));
        }
        
        chat_timer_ = nullptr;
        ESP_LOGI(TAG, "Chat timer stopped and deleted");
    }
    
    // 重置获取标志
    has_fetched_in_current_listening_ = false;
    
    ESP_LOGI(TAG, "Chat data fetching stopped successfully");
    return true;
}

void Esp32LiveStream::ChatTimerCallback(void* arg) {
    Esp32LiveStream* self = static_cast<Esp32LiveStream*>(arg);
    
    // 检查获取状态
    if (!self->is_fetching_chat_) {
        ESP_LOGD(TAG, "Chat data fetching stopped, ignoring timer callback");
        return;
    }
    
    // 获取当前设备状态
    auto& app = Application::GetInstance();
    DeviceState device_state = app.GetDeviceState();
    
    // 只有在聆听状态下才能获取数据
    if (device_state == kDeviceStateIdle || device_state == kDeviceStateListening) {
        // 检查直播是否开启状态
        if (self->streaming_) {
            // 检查是否已经在当前空闲状态下获取过数据
            if (!self->has_fetched_in_current_idle_) {
                ESP_LOGI(TAG, "Device is idle and streaming is active, fetching chat data for wake word...");
                
                // 获取聊天数据
                std::string chat_data = self->FetchChatData();
                if (!chat_data.empty()) {
                    ESP_LOGI(TAG, "Successfully fetched chat data in idle state");
                    
                    // 处理聊天数据中的文本，生成唤醒词
                    self->ProcessChatForWakeWord(chat_data);
                    
                    // 标记已获取，避免重复
                    self->has_fetched_in_current_idle_ = true;
                } else {
                    ESP_LOGI(TAG, "Failed to fetch chat data in idle state");
                }
            } else {
                ESP_LOGI(TAG, "Already fetched data in current idle state, waiting for next idle session");
            }
        } else {
            ESP_LOGI(TAG, "Device is idle but streaming is not active");
        }
    } else {
        // 如果不在聆听状态，重置获取标志和重试计数，为下次聆听做准备
        if (self->has_fetched_in_current_listening_) {
            ESP_LOGD(TAG, "Device no longer listening, resetting fetch flag and retry count for next listening session");
            self->has_fetched_in_current_listening_ = false;
            self->retry_count_ = 0;  // 重置重试计数
        }
        
        // 如果不在空闲状态，重置空闲状态的获取标志
        if (self->has_fetched_in_current_idle_) {
            ESP_LOGD(TAG, "Device no longer idle, resetting idle fetch flag for next idle session");
            self->has_fetched_in_current_idle_ = false;
        }
    }
}

bool Esp32LiveStream::ProcessChatAudioData(const std::string& json_response) {
    ESP_LOGD(TAG, "开始处理直播间音频数据...");
    
    // 解析JSON响应
    cJSON* root = cJSON_Parse(json_response.c_str());
    if (root == nullptr) {
        ESP_LOGE(TAG, "Failed to parse chat JSON response");
        return false;
    }
    
    // 获取弹幕内容并显示
    cJSON *data = cJSON_GetObjectItemCaseSensitive(root, "data");
    if (cJSON_IsObject(data)) {
        cJSON *content = cJSON_GetObjectItemCaseSensitive(data, "content");
        
        // 获取用户昵称
        const char* nick_name = "未知用户";
        cJSON *user = cJSON_GetObjectItemCaseSensitive(data, "user");
        if (cJSON_IsObject(user)) {
            cJSON *nickName = cJSON_GetObjectItemCaseSensitive(user, "nickName");
            if (cJSON_IsString(nickName)) {
                nick_name = nickName->valuestring;
            }
        }
        
        if (cJSON_IsString(content)) {
            ESP_LOGI(TAG, "收到直播间弹幕: [%s] 发言: [%s]", nick_name, content->valuestring);
             
             // 在显示屏上显示弹幕内容
             // auto& board = Board::GetInstance();
             // auto display = board.GetDisplay();
             // display->SetChatMessage("live_stream", content->valuestring);
             ESP_LOGD(TAG, "弹幕内容已显示到屏幕");
        }
    }
    
    // 获取音频数据数组
    cJSON *audio_datas = cJSON_GetObjectItemCaseSensitive(root, "audio_datas");
    if (!cJSON_IsArray(audio_datas)) {
        ESP_LOGD(TAG, "响应中没有音频数据数组");
        cJSON_Delete(root);
        return false;  // 没有音频数据，返回false触发重试
    }
    ESP_LOGD(TAG, "找到音频数据数组");

    // 获取音频信息
    cJSON *audio_duration = cJSON_GetObjectItemCaseSensitive(root, "audio_duration");
    cJSON *audio_size = cJSON_GetObjectItemCaseSensitive(root, "audio_size");
    cJSON *tts_file = cJSON_GetObjectItemCaseSensitive(root, "tts_file");
    
    if (cJSON_IsNumber(audio_duration) && cJSON_IsNumber(audio_size)) {
        ESP_LOGD(TAG, "音频信息: 时长=%.2fs, 大小=%d bytes", 
                 audio_duration->valuedouble, (int)audio_size->valuedouble);
    }

    // 处理音频数据数组
    int array_size = cJSON_GetArraySize(audio_datas);
    if (array_size > 0) {
        ESP_LOGD(TAG, "开始处理 %d 个音频数据包", array_size);
        
        for (int i = 0; i < array_size; i++) {
            cJSON *audio_item = cJSON_GetArrayItem(audio_datas, i);
            if (cJSON_IsArray(audio_item)) {
                ESP_LOGD(TAG, "处理第 %d/%d 个音频数据包", i + 1, array_size);
                
                bool send_success = ProcessSingleAudioPacket(audio_item);
                
                // 如果发送失败，尝试重试一次
                if (!send_success) {
                    ESP_LOGW(TAG, "第 %d 个音频包发送失败，500ms后重试", i + 1);
                    vTaskDelay(pdMS_TO_TICKS(20));  // 等待100ms
                    send_success = ProcessSingleAudioPacket(audio_item);
                    
                    if (!send_success) {
                        ESP_LOGE(TAG, "第 %d 个音频包重试后仍然失败，跳过", i + 1);
                        continue;
                    } else {
                        ESP_LOGD(TAG, "第 %d 个音频包重试成功", i + 1);
                    }
                }
                
                // 在音频包之间添加适当延迟，避免UDP缓冲区溢出
                if (i < array_size - 1) {  // 不是最后一个包
                    vTaskDelay(pdMS_TO_TICKS(20));  // 等待100ms
                }
                
            } else {
                ESP_LOGW(TAG, "第 %d 个音频数据包格式无效，期望数组格式", i + 1);
            }
        }
        ESP_LOGD(TAG, "所有音频数据包处理完成");
    } else {
        ESP_LOGI(TAG, "音频数据数组为空");
    }
    
    cJSON_Delete(root);
    return true;  // 成功处理了响应数据
}

bool Esp32LiveStream::ProcessSingleAudioPacket(cJSON* audio_data_array) {
    if (audio_data_array == nullptr || !cJSON_IsArray(audio_data_array)) {
        ESP_LOGW(TAG, "收到无效的音频数据数组");
        return false;
    }

    int data_len = cJSON_GetArraySize(audio_data_array);
    if (data_len == 0) {
        ESP_LOGW(TAG, "收到空的音频数据数组");
        return false;
    }

    ESP_LOGD(TAG, "🎧 开始处理音频数据包，数组长度: %d bytes", data_len);

    // 将JSON数组转换为字节数组（OPUS数据）
    std::vector<uint8_t> opus_data;
    opus_data.reserve(data_len);
    
    // 从JSON数组中提取每个字节值
    for (int i = 0; i < data_len; i++) {
        cJSON* byte_item = cJSON_GetArrayItem(audio_data_array, i);
        if (cJSON_IsNumber(byte_item)) {
            int byte_value = byte_item->valueint;
            // 确保字节值在有效范围内 (0-255)
            if (byte_value >= 0 && byte_value <= 255) {
                opus_data.push_back(static_cast<uint8_t>(byte_value));
            } else {
                ESP_LOGW(TAG, "第 %d 个字节值超出范围: %d", i, byte_value);
                opus_data.push_back(0);  // 使用默认值
            }
        } else {
            ESP_LOGW(TAG, "第 %d 个数组元素不是数字", i);
            opus_data.push_back(0);  // 使用默认值
        }
    }
    
    ESP_LOGD(TAG, "音频数据转换完成，OPUS数据大小: %d bytes", opus_data.size());

    // 创建AudioStreamPacket
    auto packet = std::make_unique<AudioStreamPacket>();
    packet->payload = std::move(opus_data);
    packet->sample_rate = 16000;     // 设置采样率
    packet->frame_duration = 60;     // 设置帧时长(ms)
    packet->timestamp = 0;           // 可以设置时间戳
    ESP_LOGD(TAG, "AudioStreamPacket创建成功 - 采样率: %dHz, 帧时长: %dms", 
             packet->sample_rate, packet->frame_duration);

    // 获取应用实例和协议对象，通过协议发送音频数据给服务器
    Protocol* protocol = &Application::GetInstance().GetProtocol();
    if (protocol) {
        ESP_LOGD(TAG, "将直播间音频数据包发送给服务器...");
        
        try {
            protocol->SendAudio(*packet);  // 解引用 unique_ptr 传递对象引用
            ESP_LOGD(TAG, "直播间音频数据包已发送给服务器，大小: %d bytes", (int)opus_data.size());
            return true;
        } catch (...) {
            ESP_LOGE(TAG, "发送音频数据包时发生异常");
            return false;
        }
    } else {
        ESP_LOGE(TAG, "无法获取协议对象，音频数据包发送失败");
        return false;
    }
}

void Esp32LiveStream::ProcessChatForWakeWord(const std::string& json_response) {
    ESP_LOGD(TAG, "开始处理直播间弹幕数据用于唤醒词...");
    
    // 解析JSON响应
    cJSON* root = cJSON_Parse(json_response.c_str());
    if (root == nullptr) {
        ESP_LOGE(TAG, "Failed to parse chat JSON response for wake word");
        return;
    }
    
    // 获取弹幕内容
    cJSON *data = cJSON_GetObjectItemCaseSensitive(root, "data");
    if (cJSON_IsObject(data)) {
        cJSON *content = cJSON_GetObjectItemCaseSensitive(data, "content");
        
        // 获取用户昵称
        const char* user_name = "未知用户";
        cJSON *user = cJSON_GetObjectItemCaseSensitive(data, "user");
        if (cJSON_IsObject(user)) {
            cJSON *nickName = cJSON_GetObjectItemCaseSensitive(user, "nickName");
            if (cJSON_IsString(nickName)) {
                user_name = nickName->valuestring;
            }
        }
        
        if (cJSON_IsString(content)) {
            // 拼接唤醒词格式
            std::string wake_word = "用户：" + std::string(user_name) + "，发送弹幕：" + std::string(content->valuestring);
            
            ESP_LOGI(TAG, "触发弹幕唤醒: %s", wake_word.c_str());
            
            // 调用唤醒词方法
            auto& app = Application::GetInstance();
            DeviceState device_state = app.GetDeviceState();
            Protocol* protocol = &Application::GetInstance().GetProtocol();

            if (device_state == kDeviceStateListening) {
                protocol->SendWakeWordDetected(wake_word);
            } else {
                app.WakeWordInvoke(wake_word);
            }
        }
    }
    
    cJSON_Delete(root);
} 